﻿namespace OPC
{
    using OPCAutomation;
    using System;
    using System.Linq;
    using System.Runtime.InteropServices;

    public class OpcHandle
    {
        private ItemsInfo[] arrItemsInfo = null;
        public bool bOPCConnected;
        private int[] g_ServerHandles;
        private static readonly OPC.OpcHandle instance = new OPC.OpcHandle();
        public string[] ItemIDs = null;
        private OPCGroup opcGroup;
        private OPCGroups opcGroups;
        private OPCItems opcItems;
        private OPCServer opcServer;

        public bool AsyncWriteItem(string argItemID, object argValue, int argTransactionID, ref int argError)
        {
            Func<ItemsInfo, bool> func = null;
            
            bool flag2;
            try
            {
                Array array;
                int num = -1;
                if ((argItemID == null) || (argValue == null))
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                int num2 = 1;
                int[] numArray = new int[num2 + 1];
                for (int i = 0; i < num2; i++)
                {
                    if (func == null)
                    {
                        func = x => x.ItemID == argItemID;
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array2 = numArray;
                object[] objArray = new object[num2 + 1];
                for (int j = 0; j < num2; j++)
                {
                    objArray[j + 1] = argValue;
                }
                Array array3 = objArray;
                this.opcGroup.AsyncWrite(num2, ref array2, ref array3, out array, argTransactionID, out num);
                bool flag = true;
                argError = Convert.ToInt32(array.GetValue(1));
                if (argError != 0)
                {
                    flag = false;
                }
                flag2 = flag;
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return flag2;
        }

        public bool ConnectPLC(string[] argsItemIDs, ref string argDescription)
        {
            try
            {
                if (argsItemIDs == null)
                {
                    throw new Exception("标签项连接字符串参数不能为 null，请检查！");
                }
                this.arrItemsInfo = new ItemsInfo[argsItemIDs.Length];
                argDescription = "创建 OPC 服务器失败！";
                this.CreateOpcServer();
                argDescription = "创建 OPC 组失败！";
                this.CreateOpcGroups();
                argDescription = "创建 OPC 标签项失败！";
                this.CreateOpcItems(argsItemIDs);
                argDescription = "创建成功！";
                this.ItemIDs = argsItemIDs;
            }
            catch (Exception exception)
            {
                argDescription = argDescription + "\n\r" + exception.ToString();
                this.bOPCConnected = false;
                this.DisOpc();
            }
            return this.bOPCConnected;
        }

        private void CreateOpcGroups()
        {
            int num = 0;
            num++;
            if (this.opcGroup == null)
            {
                this.opcGroups = this.opcServer.OPCGroups;//.get_OPCGroups();
                this.opcGroup = this.opcGroups.Add("MyGroup" + num.ToString());
                ////this.opcItems = this.opcGroup.get_OPCItems();
                ////this.opcGroup.set_IsActive(true);
                ////this.opcGroup.set_IsSubscribed(true);
                ////this.opcGroup.set_DeadBand(0f);
                ////this.opcGroup.set_UpdateRate(0x3e8);
                this.opcItems = this.opcGroup.OPCItems;//.get_OPCItems();
                this.opcGroup.IsActive=true;//.set_IsActive(true);
                this.opcGroup.IsSubscribed=true;//.set_IsSubscribed(true);
                this.opcGroup.DeadBand=0f;//.set_DeadBand(0f);
                this.opcGroup.UpdateRate=0x3e8;//.set_UpdateRate(0x3e8);
            }
        }

        private void CreateOpcItems(string[] argsItemIDs)
        {
            int num2;
            int length = argsItemIDs.Length;
            string[] strArray = new string[length + 1];
            int[] numArray = new int[length + 1];
            Array array = new int[length + 1];
            Array array2 = new int[length + 1];
            object obj2 = null;
            object obj3 = null;
            this.g_ServerHandles = new int[length + 1];
            for (num2 = 1; num2 <= length; num2++)
            {
                strArray[num2] = argsItemIDs[num2 - 1];
                numArray[num2] = num2;
                this.arrItemsInfo[num2 - 1].ItemID = argsItemIDs[num2 - 1];
                this.arrItemsInfo[num2 - 1].Index = num2;
            }
            Array array3 = strArray;
            Array array4 = numArray;
            this.opcItems = this.opcGroup.OPCItems;//.get_OPCItems();
            this.opcItems.AddItems(length, ref array3, ref array4, out array, out array2, obj2, obj3);
            if (array == null)
            {
                throw new Exception("标签项的连接字符串配置可能有误，请检查！");
            }
            for (num2 = 1; num2 <= array.Length; num2++)
            {
                this.g_ServerHandles[num2] = Convert.ToInt32(array.GetValue(num2));
                this.arrItemsInfo[num2 - 1].ItemHandle = Convert.ToInt32(array.GetValue(num2));
                if (this.arrItemsInfo[num2 - 1].ItemHandle == 0)
                {
                    throw new Exception(string.Format("标签项连接字符串存在错误，请检查！\n\r错误的标签项连接字符串：{0}。", this.arrItemsInfo[num2 - 1].ItemID));
                }
            }
        }

        private void CreateOpcServer()
        {
            Array oPCServers = null;
            if (this.opcServer == null)
            {
                this.opcServer = new OPCServerClass();
            }
            oPCServers = (Array) this.opcServer.GetOPCServers("");
            string str = "";
            for (int i = 1; i <= oPCServers.Length; i++)
            {
                if (oPCServers.GetValue(i).ToString().StartsWith("KEPware.KEPServerEx"))
                {
                    str = oPCServers.GetValue(i).ToString();
                    break;
                }
            }
            if (this.opcServer.ServerState == 6)//.get_ServerState()
            {
                this.opcServer.Connect(str, "127.0.0.1");
            }
            this.bOPCConnected = true;
        }

        public bool DisOpc()
        {
            try
            {
                this.bOPCConnected = false;
                Array array2 = this.g_ServerHandles;
                bool flag = false;
                if (this.opcItems != null)
                {
                    try
                    {
                        Array array;
                        this.opcItems.Remove(this.g_ServerHandles.Length - 1, ref array2, out array);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    this.opcItems = null;
                }
                if (this.opcGroups != null)
                {
                    this.opcGroups.Remove("MyGroup1");
                    this.opcGroups = null;
                    this.opcGroup = null;
                }
                if (this.opcServer != null)
                {
                    this.opcServer.Disconnect();
                    this.opcServer = null;
                    flag = true;
                }
                return flag;
            }
            catch
            {
                return false;
            }
        }

        ~OpcHandle()
        {
            this.DisOpc();
        }

        public static OPC.OpcHandle GetInstance()
        {
            return instance;
        }

        public string GetItemID(string argPLCName, string argDBName, string argType, string argAddress)
        {
            string str;
            argType = argType.ToUpper();
            string str3 = argType;
            if (str3 != null)
            {
                if (!(str3 == "BOOL"))
                {
                    if (str3 == "BYTE")
                    {
                        str = "B" + argAddress;
                        goto Label_00F1;
                    }
                    if (str3 == "WORD")
                    {
                        str = "W" + argAddress;
                        goto Label_00F1;
                    }
                }
                else
                {
                    str = "X" + argAddress;
                    goto Label_00F1;
                }
            }
            if (argType.StartsWith("STRING", StringComparison.CurrentCultureIgnoreCase))
            {
                str = string.Concat(new object[] { "STRING", Convert.ToInt32(argAddress), ".", argType.Substring(argType.IndexOf("[") + 1, (argType.IndexOf("]") - argType.IndexOf("[")) - 1) });
            }
            else
            {
                str = argType + argAddress;
            }
        Label_00F1:
            str3 = argDBName;
            if (str3 != null)
            {
                if (str3 == "I")
                {
                    if (argType == "BOOL")
                    {
                        str = argAddress;
                    }
                    return string.Format("{0}.{1}{2}", argPLCName, argDBName, str);
                }
                if (str3 == "Q")
                {
                    if (argType == "BOOL")
                    {
                        str = argAddress;
                    }
                    return string.Format("{0}.{1}{2}", argPLCName, argDBName, str);
                }
            }
            return string.Format("{0}.{1},{2}", argPLCName, argDBName, str);
        }

        public string[] GetItemIDs(string[] argsPLCNames, string[] argsDBNames, string[] argsTypes, string[] argsAddresss)
        {
            string[] strArray = null;
            if ((((argsPLCNames == null) || (argsDBNames == null)) || (argsTypes == null)) || (argsAddresss == null))
            {
                throw new Exception("传入的参数不能为 null，请检查！");
            }
            if (((argsPLCNames.Length != argsDBNames.Length) || (argsPLCNames.Length != argsTypes.Length)) || (argsPLCNames.Length != argsAddresss.Length))
            {
                throw new Exception("传入的参数数组元素个数必须保持一致！");
            }
            strArray = new string[argsPLCNames.Length];
            for (int i = 0; i < argsPLCNames.Length; i++)
            {
                strArray[i] = this.GetItemID(argsPLCNames[i], argsDBNames[i], argsTypes[i], argsTypes[i]);
            }
            return strArray;
        }

        public void ItemsSetActive(string[] argsItemIDs, bool argActiveState, ref int[] argsErrors)
        {
            try
            {
                Array array;
                if (argsItemIDs == null)
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                int length = argsItemIDs.Length;
                argsErrors = new int[length];
                int[] numArray = new int[length + 1];
                Func<ItemsInfo, bool> func = null;
                for (int i = 0; i < length; i++)
                {
                    if (func == null)
                    {
                        func = x => x.ItemID == argsItemIDs[i];
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array2 = numArray;
                this.opcItems.SetActive(length, ref array2, argActiveState, out array);
                for (int j = 1; j <= array.Length; j++)
                {
                    argsErrors[j - 1] = Convert.ToInt32(array.GetValue(j));
                }
            }
            catch (Exception exception)
            {
                throw exception;
            }
        }

        public object ReadItems(int argIndex, ref int argQualities)
        {
            Func<ItemsInfo, bool> func = null;
            object obj5;
            try
            {
                Array array2;
                Array array3;
                object obj2;
                object obj3;
                if (argIndex == 0)
                {
                    throw new Exception("传入的参数不能为 0！");
                }
                int num = 1;
                int[] numArray = new int[num + 1];
                for (int i = 0; i < num; i++)
                {
                    if (func == null)
                    {
                        func = x => x.Index == argIndex;
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array = numArray;
                this.opcGroup.SyncRead(1, num, ref array, out array2, out array3, out obj2, out obj3);
                Array array4 = (Array) obj2;
                argQualities = Convert.ToInt32(array4.GetValue(1));
                obj5 = array2.GetValue(1);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return obj5;
        }

        public object ReadItems(string argItemID, ref int argQualities)
        {
            Func<ItemsInfo, bool> func = null;
            object obj5;
            try
            {
                Array array2;
                Array array3;
                object obj2;
                object obj3;
                if (argItemID == null)
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                int num = 1;
                int[] numArray = new int[num + 1];
                for (int i = 0; i < num; i++)
                {
                    if (func == null)
                    {
                        func = x => x.ItemID == argItemID;
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array = numArray;
                this.opcGroup.SyncRead(1, num, ref array, out array2, out array3, out obj2, out obj3);
                Array array4 = (Array) obj2;
                argQualities = Convert.ToInt32(array4.GetValue(1));
                obj5 = array2.GetValue(1);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return obj5;
        }

        public object[] ReadItems(int[] argsIndex, ref int[] argsQualities)
        {
            object[] objArray2;
            try
            {
                Array array2;
                Array array3;
                object obj2;
                object obj3;
                if (argsIndex == null)
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                int length = argsIndex.Length;
                int[] numArray = new int[length + 1];
                argsQualities = new int[length];
                Func<ItemsInfo, bool> func = null;
                for (int i = 0; i < length; i++)
                {
                    if (func == null)
                    {
                        func = x => x.Index == argsIndex[i];
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array = numArray;
                object[] objArray = new object[length];
                this.opcGroup.SyncRead(1, length, ref array, out array2, out array3, out obj2, out obj3);
                Array array4 = (Array) obj2;
                for (int j = 1; j <= length; j++)
                {
                    argsQualities[j - 1] = Convert.ToInt32(array4.GetValue(j));
                    objArray[j - 1] = array2.GetValue(j);
                }
                objArray2 = objArray;
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return objArray2;
        }

        public object[] ReadItems(string[] argsItemIDs, ref int[] argsQualities)
        {
            object[] objArray2;
            try
            {
                Array array2;
                Array array3;
                object obj2;
                object obj3;
                if (argsItemIDs == null)
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                int length = argsItemIDs.Length;
                int[] numArray = new int[length + 1];
                argsQualities = new int[length];
                Func<ItemsInfo, bool> func = null;
                for (int i = 0; i < length; i++)
                {
                    if (func == null)
                    {
                        func = x => x.ItemID == argsItemIDs[i];
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array = numArray;
                object[] objArray = new object[length];
                this.opcGroup.SyncRead(1, length, ref array, out array2, out array3, out obj2, out obj3);
                Array array4 = (Array) obj2;
                for (int j = 1; j <= length; j++)
                {
                    argsQualities[j - 1] = Convert.ToInt32(array4.GetValue(j));
                    objArray[j - 1] = array2.GetValue(j);
                }
                objArray2 = objArray;
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return objArray2;
        }

        public bool WriteItems(int argIndex, object argValue, ref int argError)
        {
            Func<ItemsInfo, bool> func = null;
            bool flag2;
            try
            {
                Array array;
                if ((argIndex == 0) || (argValue == null))
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                int num = 1;
                int[] numArray = new int[num + 1];
                for (int i = 0; i < num; i++)
                {
                    if (func == null)
                    {
                        func = x => x.Index == argIndex;
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array2 = numArray;
                object[] objArray = new object[num + 1];
                for (int j = 0; j < num; j++)
                {
                    objArray[j + 1] = argValue;
                }
                Array array3 = objArray;
                this.opcGroup.SyncWrite(num, ref array2, ref array3, out array);
                bool flag = true;
                argError = Convert.ToInt32(array.GetValue(1));
                if (argError != 0)
                {
                    flag = false;
                }
                flag2 = flag;
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return flag2;
        }

        public bool WriteItems(string argItemID, object argValue, ref int argError)
        {
            Func<ItemsInfo, bool> func = null;
            bool flag2;
            try
            {
                Array array;
                if ((argItemID == null) || (argValue == null))
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                int num = 1;
                int[] numArray = new int[num + 1];
                for (int i = 0; i < num; i++)
                {
                    if (func == null)
                    {
                        func = x => x.ItemID == argItemID;
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array2 = numArray;
                object[] objArray = new object[num + 1];
                for (int j = 0; j < num; j++)
                {
                    objArray[j + 1] = argValue;
                }
                Array array3 = objArray;
                this.opcGroup.SyncWrite(num, ref array2, ref array3, out array);
                bool flag = true;
                argError = Convert.ToInt32(array.GetValue(1));
                if (argError != 0)
                {
                    flag = false;
                }
                flag2 = flag;
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return flag2;
        }

        public bool WriteItems(int[] argsIndex, object[] argsValues, ref int[] argsErrors)
        {
            bool flag = false;
            try
            {
                Array array;
                if ((argsIndex == null) || (argsValues == null))
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                if (argsIndex.Length != argsValues.Length)
                {
                    throw new Exception("传入的参数数组元素个数必须保持一致！");
                }
                int length = argsIndex.Length;
                argsErrors = new int[length];
                int[] numArray = new int[length + 1];
                Func<ItemsInfo, bool> func = null;
                for (int i = 0; i < length; i++)
                {
                    if (func == null)
                    {
                        func = x => (x.Index - 1) == argsIndex[i];
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array2 = numArray;
                object[] objArray = new object[length + 1];
                for (int j = 0; j < length; j++)
                {
                    objArray[j + 1] = argsValues[j];
                }
                Array array3 = objArray;
                this.opcGroup.SyncWrite(length, ref array2, ref array3, out array);
                flag = true;
                for (int k = 1; k <= array.Length; k++)
                {
                    argsErrors[k - 1] = Convert.ToInt32(array.GetValue(k));
                    if (argsErrors[k - 1] != 0)
                    {
                        return false;
                    }
                }
                return flag;
            }
            catch
            {
            }
            return flag;
        }

        public bool WriteItems(string[] argsItemIDs, object[] argsValues, ref int[] argsErrors)
        {
            bool flag2;
            try
            {
                Array array;
                if ((argsItemIDs == null) || (argsValues == null))
                {
                    throw new Exception("传入的参数不能为 null！");
                }
                if (argsItemIDs.Length != argsValues.Length)
                {
                    throw new Exception("传入的参数数组元素个数必须保持一致！");
                }
                int length = argsItemIDs.Length;
                argsErrors = new int[length];
                int[] numArray = new int[length + 1];
                Func<ItemsInfo, bool> func = null;
                for (int i = 0; i < length; i++)
                {
                    if (func == null)
                    {
                        func = x => x.ItemID == argsItemIDs[i];
                    }
                    ItemsInfo info = Enumerable.Where<ItemsInfo>(this.arrItemsInfo, func).FirstOrDefault<ItemsInfo>();
                    numArray[i + 1] = info.ItemHandle;
                }
                Array array2 = numArray;
                object[] objArray = new object[length + 1];
                for (int j = 0; j < length; j++)
                {
                    objArray[j + 1] = argsValues[j];
                }
                Array array3 = objArray;
                this.opcGroup.SyncWrite(length, ref array2, ref array3, out array);
                bool flag = true;
                for (int k = 1; k <= array.Length; k++)
                {
                    argsErrors[k - 1] = Convert.ToInt32(array.GetValue(k));
                    if (argsErrors[k - 1] != 0)
                    {
                        flag = false;
                        break;
                    }
                }
                flag2 = flag;
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return flag2;
        }

        public bool WriteItems1(string address, object argValue, ref int argError)
        {
            string argItemID = "Channel1.Device1." + address;
            return this.WriteItems(argItemID, argValue, ref argError);
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct ItemsInfo
        {
            public int Index;
            public int ItemHandle;
            public string ItemID;
        }
    }
}

